package com.brainshare.system.service.impl;

import com.brainshare.an.domain.AnWechatUser;
import com.brainshare.an.service.IAnWechatUserService;
import com.brainshare.common.constant.NumberConstants;
import com.brainshare.common.constant.UserConstants;
import com.brainshare.common.enums.*;
import com.brainshare.common.utils.DateUtils;
import com.brainshare.common.utils.SnowFlakeUtil;
import com.brainshare.common.utils.StringUtils;
import com.brainshare.system.domain.AnRedPacketRecord;
import com.brainshare.system.domain.RedPacketInfo;
import com.brainshare.system.domain.RedPacketRecord;
import com.brainshare.system.domain.vo.AddRedPacketVO;
import com.brainshare.system.domain.vo.AddWithdrawalCardVO;
import com.brainshare.system.domain.vo.RedPacketInfoVO;
import com.brainshare.system.service.*;
import com.brainshare.utils.CommonUtils;
import io.jsonwebtoken.lang.Assert;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 红包Service接口
 * @author wll
 */
@Service
public class RedPacketServiceImpl implements IRedPacketService {

    /**
     * 日志
     */
    protected final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    IRedPacketInfoService redPacketInfoService;

    @Autowired
    IRedPacketRecordService redPacketRecordService;

    @Autowired
    IAnRedPacketRecordService anRedPacketRecordService;

    @Autowired
    IAnWechatUserService anWechatUserService;

    @Override
    public synchronized AddRedPacketVO addRedPacket(HttpServletRequest request, Integer redPacketType) {
        AnWechatUser anWechatUser = CommonUtils.getAnWechatUser(request);
        Long userId = anWechatUser.getWechatUserId();
        String phone = anWechatUser.getPhone();
        return addRedPacket(userId, phone,redPacketType);
    }

    @Override
    public synchronized AddRedPacketVO addRedPacket(Long userId, String phone,Integer redPacketType) {
        long ts = DateUtils.getTimeMillis();
        try {
            logger.info("ts:{}发红包", ts);
            //入参校验
            checkParam(redPacketType);
            //分享红包次数不大于5
            Integer shareTime = NumberConstants.ONE;
            if (RedPacketType2Enum.SHARE.getCode().equals(redPacketType)) {
                List<RedPacketRecord> redPacketRecordList = getRedPacketRecordList(userId);
                if (!CollectionUtils.isEmpty(redPacketRecordList)) {
                    shareTime = redPacketRecordList.size() + 1;
                }
                if (shareTime > NumberConstants.FIVE) {
                    logger.warn("ts:{}，用户{}分享次数大于5次", ts, userId);
                    throw new Exception("分享次数大于5次");
                }
            }
            RedPacketRecord redPacketRecordParam = new RedPacketRecord();
            redPacketRecordParam.setUserId(userId);
            redPacketRecordParam.setRedPacketType2(redPacketType);
            List<RedPacketRecord> redPacketRecordList = redPacketRecordService.selectRedPacketRecordList(redPacketRecordParam);
            if (!CollectionUtils.isEmpty(redPacketRecordList)
                    && !RedPacketType2Enum.SHARE.getCode().equals(redPacketType)
            ) {
                logger.warn("ts:{}用户{}已存在{}类型红包", ts, userId, redPacketType);
                throw new Exception("用户已存在该类型红包");
            }
            //新增红包记录
            RedPacketRecord redPacketRecord = constructRedPacketRecord(userId, phone,redPacketType, shareTime);
            int recordResult = redPacketRecordService.insertRedPacketRecord(redPacketRecord);
            logger.info("ts:{}新增红包记录，结果{}", ts, recordResult);

            AddRedPacketVO addRedPacketVO = constructAddRedPacketVO(recordResult, redPacketRecord.getRedPacketAmount(),redPacketRecord.getCardType(),redPacketRecord.getRedPacketStatus());
            return addRedPacketVO;
        } catch (Exception e) {
            logger.error("ts:{},领取红包异常", ts, e);
            return null;
        }
    }

    @Override
    public Integer getShareTime(HttpServletRequest request)
    {
        AnWechatUser anWechatUser = CommonUtils.getAnWechatUser(request);
        Long userId = anWechatUser.getWechatUserId();
        List<RedPacketRecord> redPacketRecordList = getRedPacketRecordList(userId);
        if (CollectionUtils.isEmpty(redPacketRecordList)){
            return NumberConstants.ZERO;
        }
        return redPacketRecordList.size();
    }

    private List<RedPacketRecord> getRedPacketRecordList(Long userId)
    {
        RedPacketRecord redPacketRecordParam = new RedPacketRecord();
        redPacketRecordParam.setUserId(userId);
        redPacketRecordParam.setRedPacketType2(RedPacketType2Enum.SHARE.getCode());
        redPacketRecordParam.setRedPacketStatus(RedPacketStatusEnum.RECEIVED.getCode());
        List<RedPacketRecord> redPacketRecordList = redPacketRecordService.selectRedPacketRecordList(redPacketRecordParam);
        return redPacketRecordList;
    }

    private AddRedPacketVO constructAddRedPacketVO(int redPacketId,Long redPacketAmount,Integer cardType,Integer status)
    {
        AddRedPacketVO addRedPacketVO = new AddRedPacketVO();
        addRedPacketVO.setRedPacketId(String.valueOf(redPacketId));
        String amount = getYuanValue(redPacketAmount);
        addRedPacketVO.setAmount(amount);
        String randomAmount = getRandomValue(redPacketAmount);
        addRedPacketVO.setRandomAmount(randomAmount);
        addRedPacketVO.setCardType(cardType);
        addRedPacketVO.setStatus(status);

        return addRedPacketVO;
    }

    @Override
    @Transactional
    public synchronized Integer receiveRedPacket(HttpServletRequest request, Integer redPacketId) {
        AnWechatUser anWechatUser = CommonUtils.getAnWechatUser(request);
        Long userId = anWechatUser.getWechatUserId();
        String phone = anWechatUser.getPhone();
        return receiveRedPacket(userId, phone,redPacketId);
    }

    @Override
    public synchronized Integer receiveRedPacket(Long userId, String phone,Integer redPacketId) {
        long ts = DateUtils.getTimeMillis();
        try {
            logger.info("ts:{}领取红包，入参：redPacketId{}", ts, redPacketId);
            checkReceiveParamRedPacketId(redPacketId);
            RedPacketRecord redPacketRecord = redPacketRecordService.selectRedPacketRecordById(Long.valueOf(redPacketId));
            //入参校验
            checkReceiveParam(userId.intValue(),redPacketRecord);

            //更新红包记录状态
            redPacketRecord.setRedPacketStatus(RedPacketStatusEnum.RECEIVED.getCode());
            redPacketRecord.setUpdateUser(String.valueOf(userId));
            redPacketRecord.setUpdateTime(DateUtils.getNowDate());
            int updateRecordStatusResult = redPacketRecordService.updateRedPacketRecord(redPacketRecord);
            logger.info("ts:{}更新红包记录状态，结果{}", ts, updateRecordStatusResult);
            //新增或更新红包信息
            RedPacketInfo redPacketInfoParam = new RedPacketInfo();
            redPacketInfoParam.setUserId(userId);
            List<RedPacketInfo> redPacketInfoList = redPacketInfoService.selectRedPacketInfoList(redPacketInfoParam);
            if (CollectionUtils.isEmpty(redPacketInfoList)) {
                RedPacketInfo redPacketInfo = constructRedPacketInfo(userId, phone,redPacketRecord.getRedPacketAmount().intValue());
                int insertInfoResult = redPacketInfoService.insertRedPacketInfo(redPacketInfo);
                logger.info("ts:{}新增红包信息，结果{}", ts, insertInfoResult);
                if (updateRecordStatusResult > 0 && insertInfoResult > 0) {
                    return YNEnum.YES.getCode();
                } else {
                    logger.warn("ts:{}更新红包记录状态或新增红包信息失败", ts);
                    return YNEnum.NO.getCode();
                }
            }

            if (redPacketInfoList.size() > 1) {
                logger.warn("ts:{}，用户{}有多条红包记录", ts, userId);
            }

            RedPacketInfo redPacketInfo = redPacketInfoList.get(0);
            Long snatchMoney = operator(redPacketInfo.getSnatchMoney(), redPacketRecord.getRedPacketAmount(), (x, y) -> x + y);
            redPacketInfo.setSnatchMoney(snatchMoney);
            Long remindMoney = operator(redPacketInfo.getSnatchMoney(), redPacketInfo.getWithdrawalMoney(), (x, y) -> x - y);
            redPacketInfo.setRemindMoney(remindMoney);
            Long totalWithdrawalRemindMoney = operator(Long.valueOf(NumberConstants.ONE_THOUSAND), redPacketInfo.getRemindMoney(), (x, y) -> x - y);
            redPacketInfo.setTotalWithdrawalRemindMoney(totalWithdrawalRemindMoney);
            redPacketInfo.setUpdateUser(String.valueOf(userId));
            redPacketInfo.setUpdateTime(DateUtils.getNowDate());
            int updateInfoResult = redPacketInfoService.updateRedPacketInfo(redPacketInfo);
            logger.info("ts:{}更新红包信息，结果{}", ts, updateInfoResult);

            if (updateRecordStatusResult > 0 && updateInfoResult > 0) {
                return YNEnum.YES.getCode();
            } else {
                logger.warn("ts{}更新红包记录状态或更新红包信息失败", ts);
                return YNEnum.NO.getCode();
            }
        } catch (Exception e) {
            logger.error("ts:{},领取红包异常", ts, e);
            return null;
        }
    }

    @Override
    public AddRedPacketVO getRedPacketRecord(HttpServletRequest request, Integer redPacketType) {
        long ts = DateUtils.getTimeMillis();
        try {
            AnWechatUser anWechatUser = CommonUtils.getAnWechatUser(request);
            Long userId = anWechatUser.getWechatUserId();
            //入参校验
            checkParam(redPacketType);
            Assert.state(!RedPacketType2Enum.SHARE.getCode().equals(redPacketType),"异常查询");
            RedPacketRecord redPacketRecordParam = new RedPacketRecord();
            redPacketRecordParam.setUserId(userId);
            redPacketRecordParam.setRedPacketType(RedPacketTypeEnum.RED_PACKET.getCode());
            redPacketRecordParam.setRedPacketType2(redPacketType);
            List<RedPacketRecord> redPacketRecordList = redPacketRecordService.selectRedPacketRecordList(redPacketRecordParam);
            if (CollectionUtils.isEmpty(redPacketRecordList)
            ) {
                //logger.warn("ts:{}，用户{}不存在{}类型红包", ts,userId, redPacketType);
                return new AddRedPacketVO(null,null,null,null,RedPacketStatusEnum.NOT_GIVE.getCode());
            }

            if (redPacketRecordList.size()> 1) {
                logger.warn("ts:{}，用户{}存在{}个{}类型红包",ts, userId, redPacketRecordList.size(),redPacketType);
            }

            RedPacketRecord redPacketRecord=redPacketRecordList.get(0);
            // Integer amount = RedPacketType2Enum.getAmountByCode(redPacketType, null);
            // Integer cardType = amount > NumberConstants.ONE_HUNDRED ? RedPacketColorEnum.GOLD.getCode() : RedPacketColorEnum.RED.getCode();

            // 筛查红包、 完成信息填写红包、 完成体检红包的红包金额都大于1块，都是金色红包
            AddRedPacketVO addRedPacketVO = constructAddRedPacketVO(redPacketRecord.getId().intValue(),redPacketRecord.getRedPacketAmount(),RedPacketColorEnum.GOLD.getCode(),redPacketRecord.getRedPacketStatus());
            return addRedPacketVO;
        }catch (Exception e){
            logger.error("ts:{},查询红包异常", ts, e);
            return null;
        }
    }

    @Override
    public RedPacketInfoVO getRedPacketInfo(HttpServletRequest request) {
        long ts = DateUtils.getTimeMillis();
        try {
            AnWechatUser anWechatUser = CommonUtils.getAnWechatUser(request);
            Long userId = anWechatUser.getWechatUserId();
            logger.info("ts:{}，查询用户{}红包信息", ts, userId);
            RedPacketInfo redPacketInfoParam = new RedPacketInfo();
            redPacketInfoParam.setUserId(userId);
            List<RedPacketInfo> redPacketInfoList = redPacketInfoService.selectRedPacketInfoList(redPacketInfoParam);

            if (CollectionUtils.isEmpty(redPacketInfoList)) {
                logger.error("ts:{}，用户{}无红包信息", ts, userId);
                return null;
            }
            if (redPacketInfoList.size() > 1) {
                logger.error("ts:{}，用户{}有多条红包信息", ts, userId);
            }
            RedPacketInfoVO redPacketInfoVO = new RedPacketInfoVO();
            RedPacketInfo redPacketInfo = redPacketInfoList.get(0);
            logger.info("ts:{}，用户{}红包信息{}", ts, userId,redPacketInfo);
            //异常造成用户抢红包金额大于10块
            Assert.state(redPacketInfo.getSnatchMoney() < NumberConstants.ONE_THOUSAND, "系统异常，已抢钱数大于10块");
            redPacketInfoVO.setLongSnatchMoney(redPacketInfo.getSnatchMoney());
            redPacketInfoVO.setLongWithdrawalMoney(redPacketInfo.getWithdrawalMoney());
            redPacketInfoVO.setLongRemindMoney(redPacketInfo.getRemindMoney());
            handleRedPacketInfo(redPacketInfoVO);
            redPacketInfoVO.setUserId(userId);
            String nickName = anWechatUser.getNickName();
            nickName = StringUtils.isEmpty(nickName) ? UserConstants.DEFAULT_NICK_NAME : nickName;
            redPacketInfoVO.setNickName(nickName);
            int anFlag = null == anWechatUser.getIsDone() ? YNEnum.NO.getCode() : YNEnum.YES.getCode();
            redPacketInfoVO.setAnFlag(anFlag);
            Long sex = null == anWechatUser.getSex() ? Long.valueOf(SexEnum.MALE.getCode()) : anWechatUser.getSex();
            redPacketInfoVO.setSex(sex);
            Integer addEnterpriseWechatFlag = getAddEnterpriseWechatFlag(userId);
            redPacketInfoVO.setAddEnterpriseWechatFlag(addEnterpriseWechatFlag);
            logger.info("ts:{}，用户{}红包信息显示{}", ts, userId,redPacketInfoVO);

            return redPacketInfoVO;
        }catch (Exception e){
            logger.error("ts:{}，查询用户红包信息异常", ts, e);
            return null;
        }
    }

    private Integer getAddEnterpriseWechatFlag(Long userId) {
        RedPacketRecord redPacketRecord = new RedPacketRecord();
        redPacketRecord.setUserId(userId);
        redPacketRecord.setRedPacketType(RedPacketTypeEnum.WITHDRAWAL_CARD.getCode());
        redPacketRecord.setRedPacketType2(WithdrawalCardTypeEnum.ADD_ENTERPRISE_WECHAT.getCode());
        List<RedPacketRecord> redPacketRecordList = redPacketRecordService.selectRedPacketRecordList(redPacketRecord);
        if (!CollectionUtils.isEmpty(redPacketRecordList)&&redPacketRecordList.size()>1){
            logger.warn("用户:{}添加企业微信:{}有{}条提现数据",userId,WithdrawalCardTypeEnum.ADD_ENTERPRISE_WECHAT.getCode(),redPacketRecordList.size());
        }
        //List<RedPacketRecord> filterList = redPacketRecordList.stream().filter(item -> item.getRedPacketType2().equals(WithdrawalCardTypeEnum.ADD_ENTERPRISE_WECHAT.getCode())).collect(Collectors.toList());
        return CollectionUtils.isEmpty(redPacketRecordList) ? YNEnum.NO.getCode() : YNEnum.YES.getCode();
    }

    void handleRedPacketInfo(RedPacketInfoVO redPacketInfoVO) {
        Long longSnatchMoney = redPacketInfoVO.getLongSnatchMoney();
        Double doubleSnatchMoney = longSnatchMoney.doubleValue() / 100;
        String snatchMoney = String.format("%.2f", doubleSnatchMoney);
        redPacketInfoVO.setSnatchMoney(snatchMoney);

        Long longWithdrawalMoney = redPacketInfoVO.getLongWithdrawalMoney();
        Double doubleWithdrawalMoney = longWithdrawalMoney.doubleValue() / 100;
        String withdrawalMoney = String.format("%.2f", doubleWithdrawalMoney);
        redPacketInfoVO.setWithdrawalMoney(withdrawalMoney);

        Long longRemindMoney = redPacketInfoVO.getLongRemindMoney();
        Double doubleRemindMoney = longRemindMoney.doubleValue() / 100;
        String remindMoney = String.format("%.2f", doubleRemindMoney);
        redPacketInfoVO.setRemindMoney(remindMoney);
    }

    @Override
    public synchronized AddWithdrawalCardVO addWithdrawalCard(HttpServletRequest request, Integer withdrawalCardType) {
        long ts = DateUtils.getTimeMillis();
        try {
            logger.info("ts:{}新增提现卡", ts);
            checkWithdrawalParam(withdrawalCardType);
            AnWechatUser anWechatUser = CommonUtils.getAnWechatUser(request);
            Long userId = anWechatUser.getWechatUserId();
            String phone = anWechatUser.getPhone();
            RedPacketRecord redPacketRecordParam = new RedPacketRecord();
            redPacketRecordParam.setUserId(userId);
            redPacketRecordParam.setRedPacketType(RedPacketTypeEnum.WITHDRAWAL_CARD.getCode());
            redPacketRecordParam.setRedPacketType2(withdrawalCardType);
            List<RedPacketRecord> redPacketRecordList = redPacketRecordService.selectRedPacketRecordList(redPacketRecordParam);
            if (!CollectionUtils.isEmpty(redPacketRecordList)) {
                logger.info("ts:{}，用户{}已存在{}类型提现卡", ts, userId, withdrawalCardType);
                throw new Exception("用户已存在该类型提现卡");
            }
            //新增红包记录
            RedPacketRecord redPacketRecord = constructWithdrawalRecord(userId, phone,withdrawalCardType);
            int recordResult = redPacketRecordService.insertRedPacketRecord(redPacketRecord);
            logger.info("ts:{}新增提现卡记录，结果{}", ts, recordResult);
            RedPacketInfo redPacketInfo=new RedPacketInfo();
            redPacketInfo.setUserId(userId);
            List<RedPacketInfo> redPacketInfoList = redPacketInfoService.selectRedPacketInfoList(redPacketInfo);
            if (CollectionUtils.isEmpty(redPacketInfoList)){
                logger.warn("ts:{}，用户{}无红包信息",ts,userId);
                throw new Exception("用户无红包信息");
            }

            AddWithdrawalCardVO addWithdrawalCardVO= constructAddWithdrawalCardVO(recordResult,redPacketRecord.getRedPacketAmount(),redPacketInfoList.get(0).getRemindMoney(),redPacketRecord.getRedPacketStatus(),redPacketRecord.getCardType(),redPacketRecord.getOrderNo());
            return addWithdrawalCardVO;
        } catch (Exception e) {
            logger.error("ts:{},新增提现卡异常", ts, e);
            return null;
        }
    }

    private AddWithdrawalCardVO constructAddWithdrawalCardVO(int redPacketId,Long redPacketAmount,Long longRemindMoney,Integer status,Integer cardType,String orderNo)
    {
        AddWithdrawalCardVO addWithdrawalCardVO=new AddWithdrawalCardVO();
        addWithdrawalCardVO.setRedPacketId(String.valueOf(redPacketId));
        String withdrawalMoney = getYuanValue(redPacketAmount);
        addWithdrawalCardVO.setWithdrawalAmount(withdrawalMoney);
        String randomMoney = getRandomValue(redPacketAmount);
        addWithdrawalCardVO.setRandomWithdrawalAmount(randomMoney);
        String remindMoney = getYuanValue(longRemindMoney);
        addWithdrawalCardVO.setRemindMoney(remindMoney);
        addWithdrawalCardVO.setCardType(cardType);
        addWithdrawalCardVO.setStatus(status);
        addWithdrawalCardVO.setOrderNo(orderNo);

        return addWithdrawalCardVO;
    }

    private String getYuanValue(Long centMoney)
    {
        if (null==centMoney){
            return "";
        }
        Double doubleMoney = centMoney.doubleValue() / 100;
        String yuanMoney = String.format("%.2f", doubleMoney);
        return yuanMoney;
    }


    private String getRandomValue(Long centMoney)
    {
        if (null==centMoney){
            return "";
        }
        String strCentMoney = String.valueOf(centMoney);
        if (strCentMoney.length()>=3){
            return strCentMoney;
        }
        do{
            strCentMoney="0".concat(strCentMoney);
        }while (strCentMoney.length()<3);
        return strCentMoney;
    }


    @Override
    @Transactional
    public synchronized int updateWithdrawalCard( HttpServletRequest request,Integer withdrawalCardId, Integer withdrawalCardStatus) {
        long ts = DateUtils.getTimeMillis();
        try{
            AnWechatUser anWechatUser = CommonUtils.getAnWechatUser(request);
            Long userId = anWechatUser.getWechatUserId();
            logger.info("ts:{}，更新提现卡状态， withdrawalCardId:{}, withdrawalCardType:{}", ts, withdrawalCardId, withdrawalCardStatus);
            RedPacketRecord redPacketRecordParam = new RedPacketRecord();
            redPacketRecordParam.setId(Long.valueOf(withdrawalCardId));
            redPacketRecordParam.setUserId(userId);
            redPacketRecordParam.setRedPacketType(RedPacketTypeEnum.WITHDRAWAL_CARD.getCode());
            List<RedPacketRecord> redPacketRecordList = redPacketRecordService.selectRedPacketRecordList(redPacketRecordParam);
            if (CollectionUtils.isEmpty(redPacketRecordList)){
                logger.error(String.format("用户:%sID:%s的提现卡不存在",userId,withdrawalCardId));
                return YNEnum.NO.getCode();
            }
            RedPacketRecord redPacketRecord = redPacketRecordList.get(0);
            //校验入参
            checkWithdrawalStatus(withdrawalCardStatus, withdrawalCardId, redPacketRecord);
            //更新提现卡状态
            redPacketRecord.setRedPacketStatus(withdrawalCardStatus);
            redPacketRecord.setUpdateUser(String.valueOf(userId));
            redPacketRecord.setUpdateTime(DateUtils.getNowDate());
            int updateResult = redPacketRecordService.updateRedPacketRecord(redPacketRecord);
            logger.info("ts:{}更新提现卡状态，结果{}", ts, updateResult);
            if (WithdrawalCardStatusEnum.WITHDRAWAL_SUCCESS.getCode().equals(withdrawalCardStatus)) {
                RedPacketInfo redPacketInfoParam = new RedPacketInfo();
                redPacketInfoParam.setUserId(redPacketRecord.getUserId());
                List<RedPacketInfo> redPacketInfoList = redPacketInfoService.selectRedPacketInfoList(redPacketInfoParam);
                if (CollectionUtils.isEmpty(redPacketInfoList)) {
                    logger.warn("ts:{}，用户{}无红包信息", ts, redPacketInfoParam.getUserId());
                    throw new Exception("红包信息为空");
                }
                if (redPacketInfoList.size() > 1) {
                    logger.warn("ts:{}，用户{}有多条红包信息", ts, redPacketInfoParam.getUserId());
                }
                RedPacketInfo redPacketInfo = redPacketInfoList.get(0);
                Long redPacketAmount = redPacketRecord.getRedPacketAmount();
                Long withdrawalMoney = operator(redPacketInfo.getWithdrawalMoney(), redPacketAmount, (x, y) -> x + y);
                redPacketInfo.setWithdrawalMoney(withdrawalMoney);
                Long remindMoney = operator(redPacketInfo.getSnatchMoney(), withdrawalMoney, (x, y) -> x - y);
                redPacketInfo.setRemindMoney(remindMoney);
                Long totalWithdrawalRemindMoney = operator(Long.valueOf(NumberConstants.ONE_THOUSAND), remindMoney, (x, y) -> x - y);
                redPacketInfo.setTotalWithdrawalRemindMoney(totalWithdrawalRemindMoney);
                redPacketInfo.setUpdateUser(String.valueOf(userId));
                redPacketInfo.setUpdateTime(DateUtils.getNowDate());
                int updateInfoResult = redPacketInfoService.updateRedPacketInfo(redPacketInfo);
                logger.info("ts:{}，更新红包信息，结果{}", ts, updateInfoResult);
            }
            return YNEnum.YES.getCode();
        }catch (Exception e){
            logger.error("ts:{},更新提现卡状态异常", ts, e);
            return YNEnum.NO.getCode();
        }
    }

    @Override
    public AddWithdrawalCardVO getWithdrawalCardRecord(HttpServletRequest request, Integer withdrawalCardType) {
        long ts = DateUtils.getTimeMillis();
        try {
            logger.info("ts:{}，查询提现卡记录", ts);
            checkWithdrawalParam(withdrawalCardType);
            AnWechatUser anWechatUser = CommonUtils.getAnWechatUser(request);
            Long userId = anWechatUser.getWechatUserId();
            RedPacketRecord redPacketRecordParam = new RedPacketRecord();
            redPacketRecordParam.setUserId(userId);
            redPacketRecordParam.setRedPacketType(RedPacketTypeEnum.WITHDRAWAL_CARD.getCode());
            redPacketRecordParam.setRedPacketType2(withdrawalCardType);
            //List<RedPacketRecord> redPacketRecordList = redPacketRecordService.selectRedPacketRecordList(redPacketRecordParam);
            RedPacketRecord redPacketRecord = redPacketRecordService.getRedPacketRecord(redPacketRecordParam);
            if (null== redPacketRecord) {
                logger.info("ts:{}，用户{}不存在{}类型提现卡", ts, userId, withdrawalCardType);
                return new AddWithdrawalCardVO(null,null,null,null,null,WithdrawalCardStatusEnum.NOT_GIVE.getCode(),null);
                //throw new Exception("用户不存在该类型提现卡");
            }
            //if (redPacketRecordList.size()>1) {
            //    logger.info("ts:{}，用户{}存在{}个{}类型提现卡", ts, userId,redPacketRecordList.size(), withdrawalCardType);
            //}
            // RedPacketRecord redPacketRecord = redPacketRecordList.get(0);
            Integer cardType = WithdrawalCardTypeEnum.getCartTypeByCode(withdrawalCardType);
            AddWithdrawalCardVO addWithdrawalCardVO= constructAddWithdrawalCardVO(redPacketRecord.getId().intValue(),redPacketRecord.getRedPacketAmount(), redPacketRecord.getRemindMoney(),redPacketRecord.getRedPacketStatus(),cardType,redPacketRecord.getOrderNo());
            return addWithdrawalCardVO;
        } catch (Exception e) {
            logger.error("ts:{}，查询提现卡记录，异常",ts,e);
            return null;
        }
    }

    @Override
    @Transactional
    public int addAnRedPacketStep(HttpServletRequest request, String router) {
        long ts = DateUtils.getTimeMillis();
        AnWechatUser anWechatUser = CommonUtils.getAnWechatUser(request);
        Long userId = anWechatUser.getWechatUserId();
        logger.info("ts:{}，添加筛查领红包步骤，入参userId{} router{}", ts, userId, router);
        //1.修改当前步骤标识
        AnRedPacketRecord updateParam = new AnRedPacketRecord();
        updateParam.setUserId(userId);
        updateParam.setIsCurrentStep(YNEnum.YES.getCode());
        List<AnRedPacketRecord> anRedPacketRecordList = anRedPacketRecordService.selectAnRedPacketRecordList(updateParam);
        List<Long> idList = anRedPacketRecordList.stream().map(item -> item.getId()).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(idList)) {
            int updateResult = anRedPacketRecordService.updateAnRedPacketRecord(idList, String.valueOf(userId), DateUtils.getNowDate());
            logger.info("ts:{}，更新筛查领红包当前步骤标识，结果{} ", ts, updateResult);
        }
        //2.新增当前步骤
        AnRedPacketRecord insertParam = new AnRedPacketRecord();
        insertParam.setUserId(userId);
        insertParam.setRouter(router);
        insertParam.setIsCurrentStep(YNEnum.YES.getCode());
        insertParam.setCreateUser(String.valueOf(userId));
        insertParam.setCreateTime(DateUtils.getNowDate());
        insertParam.setYn(YNEnum.NO.getCode());
        int insertResult = anRedPacketRecordService.insertAnRedPacketRecord(insertParam);
        logger.info("ts:{}，新增筛查领红包步骤，结果{} ", ts, insertResult);

        return insertResult;
    }

    @Override
    public AnRedPacketRecord getCurrentAnRedPacketStep(HttpServletRequest request) {
        long ts = DateUtils.getTimeMillis();
        AnWechatUser anWechatUser = CommonUtils.getAnWechatUser(request);
        Long userId = anWechatUser.getWechatUserId();
        logger.info("ts:{}，查询筛查领红包当前步骤，入参userId{}", ts, userId);
        AnRedPacketRecord selectParam = new AnRedPacketRecord();
        selectParam.setUserId(userId);
        selectParam.setIsCurrentStep(YNEnum.YES.getCode());

        List<AnRedPacketRecord> anRedPacketRecordList = anRedPacketRecordService.selectAnRedPacketRecordList(selectParam);
        if (CollectionUtils.isEmpty(anRedPacketRecordList)) {
            logger.warn("ts:{}，用户{}无当前步骤", ts, userId);
            return null;
        }
        if (CollectionUtils.isEmpty(anRedPacketRecordList)) {
            logger.warn("ts:{}，用户{}有多个当前步骤", ts, userId);
        }
        return anRedPacketRecordList.get(0);
    }

    void checkWithdrawalStatus(Integer withdrawalCardType,Integer withdrawalCardId,RedPacketRecord redPacketRecord) {
        Assert.notNull(null == withdrawalCardType, "提现卡状态不能为空");
        Assert.state(WithdrawalCardStatusEnum.checkWithdrawalCardStatusList(withdrawalCardType), "提现卡状态不正确");
        Assert.notNull(redPacketRecord,String.format("ID%s的提现卡不存在",withdrawalCardId));
        Assert.state(withdrawalCardId==redPacketRecord.getId().intValue(), "提现卡与用户不匹配");
    }

    void checkParam(Integer redPacketType) {
        Assert.notNull(redPacketType, "红包类型不能为空");
        Assert.state(RedPacketType2Enum.checkRedPacketType(redPacketType), "红包类型错误");
    }

    void checkReceiveParamRedPacketId(Integer redPacketId) {
        Assert.notNull(redPacketId,   "红包ID不能为空");
    }

    void checkReceiveParam(  Integer userId,RedPacketRecord redPacketRecord) {
        Assert.notNull(redPacketRecord,"红包记录不存在");
        Assert.notNull(redPacketRecord.getUserId(),"红包记录用户ID异常");
        Assert.state(userId.equals(redPacketRecord.getUserId().intValue()),  "红包与用户不匹配");
        Assert.notNull(redPacketRecord.getRedPacketStatus(),"红包状态异常");
        Assert.state(!RedPacketStatusEnum.RECEIVED.getCode().equals(redPacketRecord.getRedPacketStatus()),"红包已领取过");
    }

    void checkWithdrawalParam(Integer withdrawalType) {
        Assert.notNull(withdrawalType,  "提现卡类型不能为空");
        Assert.state(WithdrawalCardTypeEnum.checkWithdrawalType(withdrawalType),  "提现卡类型错误");
    }

    RedPacketRecord constructRedPacketRecord(Long userId,String phone, int redPacketType,Integer shareTime) {
        RedPacketRecord redPacketRecord = new RedPacketRecord();
        redPacketRecord.setUserId(userId);
        redPacketRecord.setPhone(phone);
        Long amount = Long.valueOf(RedPacketType2Enum.getAmountByCode(redPacketType, shareTime));
        redPacketRecord.setRedPacketAmount(amount);
        redPacketRecord.setRedPacketType(RedPacketTypeEnum.RED_PACKET.getCode());
        redPacketRecord.setRedPacketType2(redPacketType);
        redPacketRecord.setRedPacketStatus(RedPacketStatusEnum.NOT_RECEIVED.getCode());
        redPacketRecord.setCreateUser(String.valueOf(userId));
        redPacketRecord.setCreateTime(DateUtils.getNowDate());
        Integer cardType = amount > NumberConstants.ONE_HUNDRED ? RedPacketColorEnum.GOLD.getCode() : RedPacketColorEnum.RED.getCode();
        redPacketRecord.setCardType(cardType);

        return redPacketRecord;
    }

    RedPacketRecord constructWithdrawalRecord(Long userId, String phone,int withdrawalCardType) {
        RedPacketRecord redPacketRecord = new RedPacketRecord();
        redPacketRecord.setUserId(userId);
        redPacketRecord.setPhone(phone);
        redPacketRecord.setRedPacketAmount(Long.valueOf(WithdrawalCardTypeEnum.getAmountByCode(withdrawalCardType,userId)));
        redPacketRecord.setRedPacketType(RedPacketTypeEnum.WITHDRAWAL_CARD.getCode());
        redPacketRecord.setRedPacketType2(withdrawalCardType);
        redPacketRecord.setRedPacketStatus(WithdrawalCardStatusEnum.NOT_WITHDRAWAL.getCode());
        redPacketRecord.setCardType(WithdrawalCardTypeEnum.getCartTypeByCode(withdrawalCardType));
        String orderNo= SnowFlakeUtil.getDefaultSnowFlakeId().toString();
        redPacketRecord.setOrderNo(orderNo);
        redPacketRecord.setCreateUser(String.valueOf(userId));
        redPacketRecord.setCreateTime(DateUtils.getNowDate());

        return redPacketRecord;
    }

    RedPacketInfo constructRedPacketInfo(Long userId, String phone,Integer amount) {
        RedPacketInfo redPacketInfo = new RedPacketInfo();
        redPacketInfo.setUserId(userId);
        redPacketInfo.setPhone(phone);
        redPacketInfo.setSnatchMoney(Long.valueOf(amount));
        redPacketInfo.setWithdrawalMoney(0l);
        Long remindMoney = operator(Long.valueOf(amount), Long.valueOf(NumberConstants.ZERO), (x, y) -> x - y);
        redPacketInfo.setRemindMoney(remindMoney);
        Long totalWithdrawalRemindMoney = operator(Long.valueOf(NumberConstants.ONE_THOUSAND), remindMoney, (x, y) -> x - y);
        redPacketInfo.setTotalWithdrawalRemindMoney(totalWithdrawalRemindMoney);
        redPacketInfo.setYn(YNEnum.NO.getCode());
        redPacketInfo.setCreateUser(String.valueOf(userId));
        redPacketInfo.setCreateTime(DateUtils.getNowDate());
        return redPacketInfo;
    }

    public static Long operator(Long x, Long y, OperFunction<Long, Long> of) {
        return of.operator(x, y);
    }

    @Override
    @Transactional
    public Integer clearAnRedPacketRecord() {
        long ts = DateUtils.getTimeMillis();
        try {
            logger.info("ts:{}，清理筛查领红包记录开始===========================================",ts);
            AnWechatUser user = new AnWechatUser();
            user.setIsDone(Long.valueOf(NumberConstants.ZERO));
            user.setClearFlag(YNEnum.NO.getCode());
            List<AnWechatUser> anWechatUserList = anWechatUserService.selectAnWechatUserList(user);

            if (CollectionUtils.isEmpty(anWechatUserList)) {
                logger.info("ts:{}，无完成筛查用户",ts);
                return null;
            }

            //http://192.168.1.159:8081/an/wechat_app/wechat_user/report?token=d3570dd3-23ca-419b-997c-3eb2ec194e5a&js_patientId=b59e0c947d734f2f9464d781f1ccf4
            List<Long> idList = anWechatUserList.stream().map(item -> item.getWechatUserId()).collect(Collectors.toList());
            logger.info("ts:{}，完成筛查待清理用户{}共{}个", ts,idList, idList.size());
            for (Long id : idList) {
                int anRedPacketRecordCount = anRedPacketRecordService.deleteAnRedPacketRecordByUserId(id);
                logger.info("ts:{}，用户{} 清理筛查红包记录{}条", ts, id, anRedPacketRecordCount);
                user.setWechatUserId(id);
                user.setClearFlag(YNEnum.YES.getCode());
                boolean updateAnWechatUserFlag = anWechatUserService.updateAnWechatUserInfo(user);
                logger.info("ts:{}，用户{} 更新用户清理标记结果 {}", ts, id, updateAnWechatUserFlag);
            }
            logger.info("ts:{}，清理筛查领红包记录结束===========================================",ts);
            return YNEnum.YES.getCode();
        } catch (Exception e) {
            logger.error("ts:{}，清理筛查领红包记录，异常", ts, e);
            return null;
        }

    }
}
